#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os
import shutil
import StringIO
import sys

execfile(os.path.join(sys.path[0], "framework.py"))

from oriolus.docker.repos.repository import Repository, RepositoryError
from oriolus.pith.packets.packet import FilePacket, Packet, Status
from oriolus.docker.storages.filestorage import FileStorage
from oriolus.pith.packets.meta import Meta
from oriolus.pith.packets.metareader import MetaReader
from unittest import TestCase, TestLoader, TextTestRunner

class TestRepository(TestCase):
    def setUp(self):
        self.__reader = MetaReader()
        self.__repository_path = "./testrepository"
        if os.path.exists(self.__repository_path):
            shutil.rmtree(self.__repository_path)
        os.mkdir(self.__repository_path)

    def tearDown(self):
        shutil.rmtree(self.__repository_path)

    def test_create_non_empty_storage(self):       
        rep = Repository(FileStorage(self.__repository_path))
        packets = rep.get_all()
        self.assertEqual(0, len(packets))
        rep.add(Packet(self.__create_meta1(), status=Status.BAD))
        packets1 = rep.get_all()
        self.assertEqual(1, len(packets1))
        
        rep2 = Repository(FileStorage(self.__repository_path))
        packets2 = rep.get_all()
        self.assertEqual(1, len(packets2))
        
        get_names = lambda list: [packet.name for packet in list] 
        self.assertEqual(get_names(packets1), get_names(packets2))
        
    def test_add1(self):
        rep = Repository(FileStorage(self.__repository_path))
        packets = rep.get_all()

        self.assertEqual(0, len(packets))

        rep.add(Packet(self.__create_meta1(), status=Status.BAD))

        packets = rep.get_all()
        self.assertEqual(1, len(packets))
        packet = packets[0]

        file_packet_entry = rep.find_packet_by_fullname(packet.name)
        self.assertEqual(Status.BAD, file_packet_entry.status)

        packets = rep.find_packets_by_status(Status.BAD)
        self.assertEqual(1, len(packets))
        actual_status = packets[0].status
        self.assertEqual(Status.BAD, actual_status)

    def test_add2(self):
        rep = Repository(FileStorage(self.__repository_path))
        entry_bad = Packet(self.__create_meta1(), status=Status.BAD)
        entry_installed = Packet(self.__create_meta2(), status=Status.INSTALLED)
        rep.add(entry_bad)
        rep.add(entry_installed)

        packets = rep.get_all()
        self.assertEqual(2, len(packets))
        packet_bad = rep.find_packet_by_fullname(entry_bad.name)
        self.assertEqual(Status.BAD, packet_bad.status)

        packet_installed = rep.find_packet_by_fullname(entry_installed.name)
        self.assertEqual(Status.INSTALLED, packet_installed.status)

        neighbors = rep.find_packet_neighbors_by_fullname(packet_bad.name)
        self.assertEqual(1, len(neighbors))
        self.assertEqual(neighbors[0], packet_installed.name)

    def test_add3(self):
        rep = Repository(FileStorage(self.__repository_path))
        status1 = Status.BAD
        status2 = Status.INSTALLED
        entry_status1 = Packet(self.__create_meta1(), status=status1)
        entry_status2 = Packet(self.__create_meta1(), status=status2)
        rep.add(entry_status1)

        self.assertRaises(RepositoryError, rep.add, entry_status2)

        packets = rep.get_all()
        self.assertEqual(1, len(packets))
        packet_in_repository = rep.find_packet_by_fullname(entry_status1.name)
        self.assertEqual(status1, packet_in_repository.status)

    def test_find_packets_by_name1(self):
        rep = Repository(FileStorage(self.__repository_path))
        entry_bad = Packet(self.__create_meta1(), status=Status.BAD)
        entry_installed = Packet(self.__create_meta2(), status=Status.INSTALLED)
        rep.add(entry_bad)
        rep.add(entry_installed)

        packets = rep.find_packets_by_name("test_packet")
        self.assertEqual(1, len(packets))
        self.assertEqual(entry_bad.name, packets[0].name)

    def test_find_packets_by_name2(self):
        rep = Repository(FileStorage(self.__repository_path))
        entry_bad = Packet(self.__create_meta1(), status=Status.BAD)
        entry_bad2 = Packet(self.__create_meta3(), status=Status.BAD)
        entry_installed = Packet(self.__create_meta2(), status=Status.INSTALLED)
        rep.add(entry_bad)
        rep.add(entry_bad2)
        rep.add(entry_installed)

        packets = rep.find_packets_by_name("test_packet")
        self.assertEqual(2, len(packets))
        self.assertEqual(entry_bad.meta.name, packets[0].meta.name)
        self.assertEqual(entry_bad.meta.name, packets[1].meta.name)

    def test_get_status_of_packet1(self):
        rep = Repository(FileStorage(self.__repository_path))
        packet = Packet(self.__create_meta1(), status=Status.BAD)

        rep.add(packet)
        packet_status = rep.get_status(packet.name)
        self.assertEqual(packet_status, packet.status)

    def test_update(self):
        rep = Repository(FileStorage(self.__repository_path))
        packet = Packet(self.__create_meta1(), status=Status.BAD)

        rep.add(packet)

        packet_status = rep.get_status(packet.name)
        self.assertEqual(packet_status, packet.status)

        packet.status = Status.INSTALLED
        
        rep.update(packet)

        packet_status = rep.get_status(packet.name)
        self.assertEqual(packet_status, Status.INSTALLED)
        self.assertEqual(1, len(rep.get_all()))

        packets = rep.find_packets_by_status(Status.INSTALLED)
        self.assertEqual(1, len(packets))
        self.assertEqual(packet.name, packets[0].name)

    def test_remove1(self):
        rep = Repository(FileStorage(self.__repository_path))
        packet = Packet(self.__create_meta1(), status=Status.BAD)
        packet_to_remove = Packet(self.__create_meta2(), status=Status.INSTALLED)
        rep.add(packet)
        rep.add(packet_to_remove)
               
        self.assertEqual(4, len(os.listdir(self.__repository_path)))
        self.assertEqual(2, len(rep.get_all()))

        rep.remove(packet_to_remove.name)
        self.assertEqual(2, len(os.listdir(self.__repository_path)))
        self.assertEqual(1, len(rep.get_all()))

    def test_find_children1(self):
        packet1 = Packet(self.__create_meta1(), status=Status.INSTALLED)
        packet2 = Packet(self.__create_meta3(), status=Status.INSTALLED)
        packet3 = Packet(self.__create_meta4(), status=Status.INSTALLED)
        
        rep = Repository(FileStorage(self.__repository_path))
        rep.add(packet1)
        rep.add(packet2)
        rep.add(packet3)

        self.assertEqual(3, len(rep.get_all()))
        packet1_entry, packet2_entry = rep.find_child_packets(packet3.name)
        self.assertEqual(packet1_entry.name, packet1.name)
        self.assertEqual(packet1_entry.status, packet1.status)
        self.assertEqual(packet1_entry.meta, packet1.meta)
        self.assertEqual(packet1_entry.basepath, packet1.basepath)
        
        self.assertEqual(packet2_entry.name, packet2.name)
        self.assertEqual(packet2_entry.status, packet2.status)
        self.assertEqual(packet2_entry.meta, packet2.meta)
        self.assertEqual(packet2_entry.basepath, packet2.basepath)

    def test_find_children2(self):
        rep = Repository(FileStorage(self.__repository_path))
        self.assertEqual([], rep.find_child_packets("foo_packet"))

    def __create_meta1(self):
        packet = """
name : test_packet
version : 1.2.3.4
description : Some test for Shtrih-M
conflicts : [{Name: test_packet_lake, Version: 1.2.0.0}]
replaces: [{Name: test_packet, Version: "(,10.0.0.1]"}]
depends:
- Name: foo_packet
  Version: "(1.2.3.0, 3.0.0]"
- Name: fake_packet
  Version: "(, 1.2.3.4]"
- Name: fake_packet2
  Version: "[1.0, 1.2]" """

        return self.__reader.read(StringIO.StringIO(packet))

    def __create_meta2(self):
        packet = """
name : fake_packet2
version : 1.1.1.1
description : Some test for Shtrih-M
conflicts : [{Name: test_packet_lake, Version: 1.2.0.0}]
replaces: [{Name: test_packet, Version: "(,10.0.0.1]"}]
depends:
- Name: foo_packet
  Version: "(1.2.3.0, 3.0.0]"
- Name: fake_packet
  Version: "(, 1.2.3.4]"
- Name: fake_packet3
  Version: "[1.0, 1.2]" """

        return self.__reader.read(StringIO.StringIO(packet))

    def __create_meta3(self):
        packet = """
name : test_packet
version : 2.2.2.2
description : Some test for Shtrih-M
conflicts : [{Name: test_packet_lake, Version: 1.2.0.0}]
replaces: [{Name: test_packet, Version: "(,10.0.0.1]"}]
depends:
- Name: foo_packet
  Version: "(1.2.3.0, 3.0.0]"
- Name: fake_packet
  Version: "(, 1.2.3.4]"
- Name: fake_packet3
  Version: "[1.0, 1.2]" """

        return self.__reader.read(StringIO.StringIO(packet))

    def __create_meta4(self):
        packet = """
name : foo_packet
version : 2.2.2.2
description : Some test for Shtrih-M
conflicts : [{Name: test_packet_lake, Version: 1.2.0.0}]
replaces: [{Name: test_packet, Version: "(,10.0.0.1]"}]
depends:
- Name: fake_packet
  Version: "(, 1.2.3.4]"
- Name: fake_packet3
  Version: "[1.0, 1.2]" """

        return self.__reader.read(StringIO.StringIO(packet))

if __name__ == "__main__":
    suite = TestLoader().loadTestsFromTestCase(TestRepository)
    TextTestRunner(verbosity=2).run(suite)
